package com.liting.uitest.service.impl;

import com.liting.uitest.imgutils.*;
import com.liting.uitest.model.*;
import com.liting.uitest.utils.FileUtil;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 界面评价方法门面类
 */
@Service
public class ImageTestServiceImpl {
    @Autowired
    private ImageCacheService cacheService;
    @Autowired
    private WhiteSpace whiteSpace;
    @Autowired
    private VerticaSymmetry verticaSymmetry;
    @Autowired
    private Balance balance;
    @Autowired
    private Proportion proportion;
    @Autowired
    private UNCalc unCalc;
    @Autowired
    private SimplicityCalc simplicityCalc;
    @Autowired
    private VisionIntensionService intensionService;


    public BigDecimal imageEntropy(Long id) throws Exception {
        File imgFile = null;

        ImageInfo imageInfo = cacheService.getImage(id);
        imgFile = new File(imageInfo.getAbsultPath());
        BufferedImage image = ImageIO.read(imgFile);
        double entropy2 = ImageEntropy.calculateEntropy1(image);
        BigDecimal result = new BigDecimal(entropy2).setScale(2, RoundingMode.UP);

        cacheService.addImageTestResult(id, "imageEntropy", result);
        return result;

    }

    public BigDecimal imageWhiteSpace(Long id, List<Rectangle> rectList, List<Circle> cirList) throws Exception {
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }
        BigDecimal result = whiteSpace.whiteSpaceCalc(id, rectList, cirList);

        cacheService.addImageTestResult(id, "imageWhiteSpace", result);

        return result;

    }

    public BigDecimal vsCalc(Long id, List<Rectangle> rectList, List<Circle> cirList) throws Exception {
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }
        BigDecimal result = verticaSymmetry.vsCalc(id, rectList, cirList);

        cacheService.addImageTestResult(id, "vsCalc", result);

        return result;
    }

    public BigDecimal baCalc(Long id, List<Rectangle> rectList, List<Circle> cirList) throws Exception {
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }
        BigDecimal result = balance.baCalc(id, rectList, cirList);

        cacheService.addImageTestResult(id, "baCalc", result);

        return result;
    }

    public BigDecimal proportionCalc(Long id, List<Rectangle> rectList, List<Circle> cirList) throws Exception {
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }
        BigDecimal result = proportion.proportionCalc(id, rectList, cirList);
        cacheService.addImageTestResult(id, "proportionCalc", result);
        return result;
    }

    public BigDecimal unCalc(Long id, List<Rectangle> rectList, List<Circle> cirList) throws Exception {
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }
        BigDecimal result = unCalc.unCalc(id, rectList, cirList);
        cacheService.addImageTestResult(id, "unCalc", result);
        return result;
    }

    public BigDecimal siCalc(Long id, List<Rectangle> rectList, List<Circle> cirList) throws Exception {
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }
        BigDecimal result = simplicityCalc.siCalc(id, rectList, cirList);
        cacheService.addImageTestResult(id, "siCalc", result);
        return result;
    }

    public BigDecimal visionCalc(VisionModule visionModule) throws Exception {
        ImageModule imageInfo = visionModule.getImageModule();
        List<Rectangle> rectList = imageInfo.getRectList();
        List<Circle> cirList = imageInfo.getCirList();
        if (rectList == null) {
            rectList = new ArrayList<>();
        }
        if (cirList == null) {
            cirList = new ArrayList<>();
        }

        BigDecimal result = intensionService.visionIntentCalc(imageInfo.getId(), visionModule.getLength(), rectList, cirList, visionModule.getModuleImportList());
        cacheService.addImageTestResult(imageInfo.getId(), "visionCalc", result);
        return result;
    }

    public BigDecimal imageColorDistance(Long id) {
        ImageInfo imageInfo = cacheService.getImage(id);
        Mat srcImage = imageInfo.getColorImage();
        double distance = MinMaxPixel.getColorDistance(srcImage);

        BigDecimal result = new BigDecimal(distance).setScale(2, RoundingMode.UP);

        cacheService.addImageTestResult(id, "imageColorDistance", result);

        return result;

    }

    public Map<String, BigDecimal> imagePartColorDistance(Long id, List<Rectangle> rectList, List<Circle> cirList) {
        ImageInfo imageInfo = cacheService.getImage(id);
        Mat srcImage = imageInfo.getColorImage();

        Map<String, BigDecimal> result = new HashMap<>();
        if (cirList != null) {
            for (Circle circle : cirList) {
                Mat cirDest = OpenCVImageUtils.getCircle(srcImage, circle);
                double distance = MinMaxPixel.getColorDistance(cirDest);

                result.put(circle.getName(), new BigDecimal(distance).setScale(2, RoundingMode.UP));
            }
        }

        if (rectList != null) {
            for (Rectangle rectangle : rectList) {
                Mat dectDest = OpenCVImageUtils.getRect(srcImage, rectangle);
                double distance = MinMaxPixel.getColorDistance(dectDest);

                result.put(rectangle.getName(), new BigDecimal(distance).setScale(2, RoundingMode.UP));
            }
        }

        cacheService.addImageTestResult(id, "imagePartColorDistance", result);

        return result;

    }

    public Map<String, Object> imageTestReport(Long id) {
        Map<String, Object> result = cacheService.getImageTestMap(id);

        return result;
    }
}
